package common

import (
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/sirupsen/logrus"
)

////////////////////////////////////////////////////////////////////////////////////////////////////

var logger *logrus.Logger

////////////////////////////////////////////////////////////////////////////////////////////////////

// FileLineHook 实现了 logrus 的 Hook 接口
type FileLineHook struct{}

// -------------------------------------------------------------------------------------------------
// 返回该 Hook 应该添加到哪些日志级别
// -------------------------------------------------------------------------------------------------
func (hook *FileLineHook) Levels() []logrus.Level {
	return logrus.AllLevels
}

// -------------------------------------------------------------------------------------------------
// 处理文件路径，只保留从最后三级目录开始的路径部分
// -------------------------------------------------------------------------------------------------
func getRelativePath(fullPath string) string {
	// 转换路径分隔符，确保跨平台兼容性
	normalizedPath := filepath.ToSlash(fullPath)

	// 将路径按分隔符分割成切片
	parts := strings.Split(normalizedPath, "/")

	// 获取最后三级目录
	if len(parts) > 3 {
		// 保留从最后三级目录开始的部分
		parts = parts[len(parts)-3:]
	}

	// 拼接为路径
	return "/" + strings.Join(parts, "/")
}

// -------------------------------------------------------------------------------------------------
// 在每个日志条目中插入文件名、函数名和行号
// -------------------------------------------------------------------------------------------------
func (hook *FileLineHook) Fire(entry *logrus.Entry) error {
	pc := make([]uintptr, 10) // 最多获取 10 层调用栈
	n := runtime.Callers(2, pc)
	frames := runtime.CallersFrames(pc[:n])

	for {
		frame, more := frames.Next()
		if !more {
			break
		}

		// 跳过 logrus 包的调用栈
		if strings.Contains(frame.File, "logrus") {
			continue
		}

		entry.Data["file"] = getRelativePath(frame.File)
		entry.Data["line"] = frame.Line
		entry.Data["func"] = frame.Function
		break
	}
	return nil
}

type CustomFormatter struct{}

// -------------------------------------------------------------------------------------------------
// 自定义格式化逻辑
// -------------------------------------------------------------------------------------------------
func (f *CustomFormatter) Format(entry *logrus.Entry) ([]byte, error) {
	timestamp := entry.Time.Format("2006-01-02 15:04:05.000")

	// 从 entry.Data 中提取 module，如果不存在则提供一个默认值
	module, ok := entry.Data["module"].(string)
	if !ok {
		module = "unknown" // 提供一个默认值以防万一
	}

	// 构建字段信息
	fields := make([]string, 0, len(entry.Data))
	for key, value := range entry.Data {
		if key == "file" || key == "line" || key == "func" || key == "module" {
			continue
		}
		fields = append(fields, fmt.Sprintf("%s=%v", key, value))
	}

	msg := ""
	if len(fields) == 0 {
		msg = fmt.Sprintf("%s [%s] [%s] %s [%s:%d]\n",
			timestamp,
			entry.Level.String(),
			module,
			entry.Message,
			entry.Data["file"],
			entry.Data["line"],
		)
	} else {
		msg = fmt.Sprintf("%s [%s] [%s] %s {%s} [%s:%d]\n",
			timestamp,
			entry.Level.String(),
			module,
			entry.Message,
			strings.Join(fields, " "),
			entry.Data["file"],
			entry.Data["line"],
		)
	}

	return []byte(msg), nil
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func InitLogger() {
	logger = logrus.New()

	// 添加自定义 Hook 用于自动记录文件和行号
	logger.AddHook(&FileLineHook{})

	// 设置自定义日志格式
	logger.SetFormatter(&CustomFormatter{})

	// 设置日志输出
	logger.SetOutput(os.Stdout)

	// 设置日志级别
	logger.SetLevel(logrus.InfoLevel)
}

// -------------------------------------------------------------------------------------------------
//
// -------------------------------------------------------------------------------------------------
func Logger(module string, rid ...string) *logrus.Entry {
	entry := logger.WithField("module", module)

	if len(rid) == 0 || rid[0] == "" {
		return entry
	} else {
		return entry.WithField("rid", rid[0])
	}
}
